﻿namespace VIT.BusinessLogicLayer
{
    using System;
    using System.Collections.Generic;
    using System.Data.Objects;
    using System.Linq;

    using VIT.DataAccessLayer;
    using VIT.DataTransferObjects.Presentation;
    using VIT.Entity;
    using VIT.Library;
    using VIT.Library.Web;

    public class ArticleBLL : BLLBase
    {
        private readonly ICategoryLanguageDAL _categoryLanguageDAL;
        private readonly IArticleDAL _articleDAL;
        private readonly ITypeArticleDAL _articleTypeDAL;
        private readonly IArticleLanguageDAL _articleLanguageDAL;
        private readonly IItemCommentDAL _ItemCommentDAL;

        private readonly string _domainStore;
        private readonly string _imagePathThumb;
        private readonly string _imagePathDetail;

        private readonly URL _url;

        public const string CategoryType = "ART";

        #region Constructor
        public ArticleBLL(string connectionString = "")
            : base(connectionString)
        {
            this._categoryLanguageDAL = new CategoryLanguageDAL(this.DatabaseFactory);
            this._articleDAL = new ArticleDAL(this.DatabaseFactory);
            this._articleTypeDAL = new TypeArticleDAL(this.DatabaseFactory);
            this._articleLanguageDAL = new ArticleLanguageDAL(DatabaseFactory);
            this._ItemCommentDAL = new ItemCommentDAL(this.DatabaseFactory);

            this._imagePathThumb = SettingsManager.Constants.LinkArticleThumbImage;
            this._imagePathDetail = SettingsManager.Constants.LinkArticleDetailImage;
            this._domainStore = SettingsManager.AppSettings.DomainStore;

            this._url = new URL();
        }
        #endregion

        #region Function
        public List<ArticlesWithImageViewsDto> GetListArticlesWithImageViews(int companyId, string languageId, int categoryId, bool inChildCat, string types, bool hasFavourite, bool hasRandom, string tag, int ortherId, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this.GetQueryArticles(companyId, languageId, categoryId, inChildCat, types, hasFavourite, tag, ortherId);
                
            var articles = query.Select(a => new ArticlesWithImageViewsDto
                {
                    Id = a.ArticleId,
                    Title = a.Title,
                    Description = a.Brief,
                    Likes = a.Article.Item.ItemLike == null ? 0 : a.Article.Item.ItemLike.Likes,
                    UnLikes = a.Article.Item.ItemLike == null ? 0 : a.Article.Item.ItemLike.UnLikes,
                    VoteNumber = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteNumber,
                    VoteRate = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteRate,
                    Image = a.Article.Image,
                    Time = a.Article.DisplayDate ?? DateTime.Now,
                    Views = a.Article.Item.ItemView == null ? 0 : a.Article.Item.ItemView.Views,
                });

            if (hasRandom)
            {
                //var random = new Random();
                //var seed = random.Next();
                //articles = articles.OrderBy(o => (~(o.Id & seed)) & (o.Id | seed));
                articles = articles.OrderBy(o => Guid.NewGuid());
            }

            totalPage = articles.Count();
            if (Skip > 0) articles = articles.Skip(Skip);
            if (Take > 0) articles = articles.Take(Take);

            var data = articles.ToList();

            var imagePathDetail = string.Format(this._imagePathDetail, companyId);
            var imagePathThumb = string.Format(this._imagePathThumb, companyId);
            foreach (var article in data)
            {
                if (!string.IsNullOrEmpty(article.Image))
                {
                    article.ImagePathDetail = this._url.VirtualPath(imagePathDetail + article.Image);
                    article.ImagePathThumb = this._url.VirtualPath(imagePathThumb + article.Image);
                }
            }
            return data;
        }
        public List<ArticlesWithImageDto> GetListArticlesWithImage(int companyId, string languageId, int categoryId, bool inChildCat, string types, bool hasFavourite, string tag, int ortherId, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this.GetQueryArticles(companyId, languageId, categoryId, inChildCat, types, hasFavourite, tag, ortherId);

            var articles = query.Select(a => new ArticlesWithImageDto
            {
                Id = a.ArticleId,
                Title = a.Title,
                Description = a.Brief,
                Image = a.Article.Image,
                Time = a.Article.DisplayDate ?? DateTime.Now,
            });

            totalPage = articles.Count();
            if (Skip > 0) articles = articles.Skip(Skip);
            if (Take > 0) articles = articles.Take(Take);

            var data = articles.ToList();
            var imagePathDetail = string.Format(this._imagePathDetail, companyId);
            var imagePathThumb = string.Format(this._imagePathThumb, companyId); foreach (var article in data)
            {
                article.ImagePathDetail = this._url.VirtualPath(imagePathDetail + article.Image);
                article.ImagePathThumb = this._url.VirtualPath(imagePathThumb + article.Image);
            }
            return data;
        }
        public List<ArticlesWithViewsDto> GetListArticlesWithViews(int companyId, string languageId, int categoryId, bool inChildCat, string types, bool hasFavourite, bool hasRandom, string tag, int ortherId, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this.GetQueryArticles(companyId, languageId, categoryId, inChildCat, types, hasFavourite, tag, ortherId);

            var articles = query.Select(a => new ArticlesWithViewsDto
            {
                Id = a.ArticleId,
                Title = a.Title,
                Description = a.Brief,
                Likes = a.Article.Item.ItemLike == null ? 0 : a.Article.Item.ItemLike.Likes,
                UnLikes = a.Article.Item.ItemLike == null ? 0 : a.Article.Item.ItemLike.UnLikes,
                VoteNumber = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteNumber,
                VoteRate = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteRate,
                Views = a.Article.Item.ItemView == null ? 0 : a.Article.Item.ItemView.Views,
            });

            if (hasRandom)
            {
                //var random = new Random();
                //var seed = random.Next();
                //articles = articles.OrderBy(o => (~(o.Id & seed)) & (o.Id | seed));
                articles = articles.OrderBy(o => Guid.NewGuid());
            }

            totalPage = articles.Count();
            if (Skip > 0) articles = articles.Skip(Skip);
            if (Take > 0) articles = articles.Take(Take);
            var data = articles.ToList();
            return data;
        }

        public List<ArticlesWithTitleDto> GetListArticlesWithTitle(int companyId, string languageId, int categoryId, bool inChildCat, string types, bool hasFavourite, string tag, int ortherId, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this.GetQueryArticles(companyId, languageId, categoryId, inChildCat, types, hasFavourite, tag, ortherId);

            var articles = query.Select(a => new ArticlesWithTitleDto
            {
                Id = a.ArticleId,
                Title = a.Title,
                Description = a.Brief
            });

            totalPage = articles.Count();
            if (Skip > 0) articles = articles.Skip(Skip);
            if (Take > 0) articles = articles.Take(Take);

            var data = articles.ToList();
            return data;
        }

        public List<DataSimpleDto> SearchDataSimple(int companyId, string languageId, string key, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this.GetQueryArticles(companyId, languageId, 0, true, string.Empty, false, string.Empty, 0);
            query = query.Where(e => e.Title.Contains(key) || e.Brief.Contains(key));

            var articles = query.Select(a => new DataSimpleDto
            {
                Id = a.ArticleId,
                CategoryId = a.Article.CategoryId,
                Title = a.Title,
                Description = a.Brief,
                ImagePath = a.Article.Image
            });

            totalPage = articles.Count();
            if (Skip > 0) articles = articles.Skip(Skip);
            if (Take > 0) articles = articles.Take(Take);

            var data = articles.ToList();

            var imagePathThumb = string.Format(this._imagePathThumb, companyId);
            foreach (var article in data)
            {
                article.ImagePath = this._url.VirtualPath(imagePathThumb + article.ImagePath);
            }

            return data;
        }

        public List<DataSimpleDto> GetDataSimple(int companyId, string languageId, int categoryId, bool inChildCat, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this.GetQueryArticles(companyId, languageId, categoryId, inChildCat, string.Empty, false, string.Empty, 0);

            var articles = query.Select(a => new DataSimpleDto
            {
                Id = a.ArticleId,
                CategoryId = a.Article.CategoryId,
                Title = a.Title,
                Description = a.Brief,
                ImagePath = a.Article.Image
            });

            totalPage = articles.Count();
            if (Skip > 0) articles = articles.Skip(Skip);
            if (Take > 0) articles = articles.Take(Take);

            var data = articles.ToList();

            var imagePathThumb = string.Format(this._imagePathThumb, companyId);
            foreach (var article in data)
            {
                if (!string.IsNullOrEmpty(article.ImagePath))
                {
                    article.ImagePath = this._url.VirtualPath(imagePathThumb + article.ImagePath);
                }
            }

            return data;
        }

        public List<TypeDto> GetTypes(int companyId)
        {
            var query = this._articleTypeDAL.GetAll().Where(e => e.CompanyId == companyId)
                .Select(e => new TypeDto
                {
                    Code = e.Id,
                    Name = e.Description
                });

            var data = query.ToList();

            return data;
        }

        public List<ArticleItemCategoryDto> GetArticleWithCategoryList(int categoryId, bool inChildCat, string languageId, int companyId, string types, bool hasFavourite, string tag, int ortherId, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this._articleLanguageDAL.GetAllIncludeViewCategory()
                .Where(c => c.LanguageId == languageId)
                .Where(c => c.Article.Item.IsPublished && c.Article.Item.CompanyId == companyId);

            if (ortherId > 0)
                query = query.Where(language => language.ArticleId != ortherId);

            if (!string.IsNullOrEmpty(tag))
            {
                var arrTag = tag.Split('_');
                query = arrTag.Aggregate(query, (current, t) => current.Where(c => c.Article.Tag.Contains(t)));
            }

            if (hasFavourite)
                query = query.OrderBy(language => language.Article.Item.ItemView.Views / ((EntityFunctions.DiffDays((language.Article.Item.ModifyDate ?? language.Article.Item.CreateDate), DateTime.Now) ?? 1) + 1));
            else
                query = query.OrderBy(language => language.Article.Item.Orders)
                    .ThenByDescending(language => language.Article.Item.ModifyDate ?? language.Article.Item.CreateDate)
                    .ThenBy(language => language.Article.CategoryId);

            if (!string.IsNullOrEmpty(types))
            {
                var arrType = types.Split(',');
                query = arrType.Aggregate(query, (current, type) => current.Where(c => c.Article.Type.Contains(type)));
            }

            if (categoryId > 0)
            {
                IList<int> listCategory;
                if (inChildCat)
                {
                    var categorys = this._categoryLanguageDAL.GetAllIncludeItem()
                        .Where(cat => cat.Category.Item.IsPublished && cat.LanguageId == languageId)
                        .Select(cat => new CategorySimpleDto
                        {
                            ID = cat.CategoryId,
                            Title = cat.Title,
                            ParentId = cat.Category.ParentId
                        }).ToList();

                    listCategory = this.GetAllChildId(categorys, categoryId);
                }
                else
                {
                    listCategory = new List<int>();
                }
                listCategory.Add(categoryId);

                query = query.Where(c => listCategory.Contains(c.Article.CategoryId));
            }

            var articles = query.Select(a => new ArticleItemCategoryDto
            {
                Id = a.ArticleId,
                CategoryId = a.Article.CategoryId,
                CategoryTitle = a.Article.Category.CategoryLanguages.FirstOrDefault(categoryLanguage => categoryLanguage.LanguageId == languageId).Title,
                Title = a.Title,
                Views = a.Article.Item.ItemView == null ? 0 : a.Article.Item.ItemView.Views,
                Likes = a.Article.Item.ItemLike == null ? 0 : a.Article.Item.ItemLike.Likes,
                Published = a.Article.Item.IsPublished,
                Unlike = a.Article.Item.ItemLike == null ? 0 : a.Article.Item.ItemLike.UnLikes,
                Brief = a.Brief,
                ImageName = a.Article.Image
            });

            totalPage = articles.Count();
            var r = articles.Skip(Skip);
            if (Take > 0) r = r.Take(Take);

            var data = r.ToList();

            var imagePathThumb = string.Format(this._imagePathThumb, companyId);
            data.ForEach(dto => dto.ImagePathThumb = this._url.VirtualPath(imagePathThumb + dto.ImageName));

            return data;
        }

        public List<ArticlesWithImageViewsDto> GetOrther(int companyId, int ortherId, OrtherType ortherType, out int totalPage, int skip = 0, int take = 0, string languageId = "vi-VN")
        {
            try
            {
                var item = this._articleDAL.GetAll()
                    .Where(e => e.Id == ortherId)
                    .Select(e => new { e.CategoryId, e.DisplayDate })
                    .FirstOrDefault();
                if (item == null)
                {
                    totalPage = 0;
                    return new List<ArticlesWithImageViewsDto>();
                }

                var query = this._articleLanguageDAL.GetAllIncludeItemView()
                    .Where(c => c.LanguageId == languageId && c.ArticleId != ortherId)
                    .Where(c => c.Article.CategoryId == item.CategoryId)
                    .Where(c => c.Article.Item.IsPublished);

                switch (ortherType)
                {
                    case OrtherType.First:
                        query = query.Where(language => language.Article.DisplayDate < item.DisplayDate)
                            .OrderByDescending(o => o.Article.DisplayDate);
                        break;
                    case OrtherType.Last:
                        query = query.Where(language => language.Article.DisplayDate > item.DisplayDate)
                            .OrderBy(o => o.Article.DisplayDate);
                        break;
                }

                var articles = query.Select(a => new ArticlesWithImageViewsDto
                {
                    Id = a.ArticleId,
                    Title = a.Title,
                    Description = a.Brief,
                    VoteNumber = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteNumber,
                    VoteRate = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteRate,
                    Image = a.Article.Image,
                    Time = a.Article.DisplayDate ?? DateTime.Now,
                    Views = a.Article.Item.ItemView == null ? 0 : a.Article.Item.ItemView.Views,
                });

                var imagePathDetail = string.Format(this._imagePathDetail, companyId);
                var imagePathThumb = string.Format(this._imagePathThumb, companyId);

                foreach (var article in articles)
                {
                    article.ImagePathDetail = this._url.VirtualPath(imagePathDetail + article.Image);
                    article.ImagePathThumb = this._url.VirtualPath(imagePathThumb + article.Image);
                }

                totalPage = articles.Count();
                var r = articles.Skip(skip);
                if (take > 0) r = r.Take(take);

                var data = r.ToList();

                foreach (var article in data)
                {
                    article.ImagePathDetail = this._url.VirtualPath(imagePathDetail + article.Image);
                    article.ImagePathThumb = this._url.VirtualPath(imagePathThumb + article.Image);
                }
                return data;
            }
            catch (Exception ex)
            {
                throw new BusinessLogicLayerException(ex.Message);
            }
        }

        public int GetCategoryIdByArticleId(int companyId, int productId)
        {
            var query = this._articleDAL.GetAll()
                .Where(e => e.Item.CompanyId == companyId && e.Id == productId)
                .Select(e => e.CategoryId);

            var data = query.FirstOrDefault();

            return data;
        }

        public List<ArticlesWithImageViewsDto> GetArticleByCategory(int categoryId, string languageId, int companyId, out int totalPage, int Skip = 0, int Take = 0)
        {
            var articles = this._articleLanguageDAL.GetAllIncludeItemView()
                .Where(c => c.LanguageId == languageId)
                .Where(c => c.Article.CategoryId == categoryId)
                .Where(c => c.Article.Item.IsPublished && c.Article.Item.CompanyId == companyId)
                .Select(a => new ArticlesWithImageViewsDto
                {
                    Id = a.ArticleId,
                    Title = a.Title,
                    Description = a.Brief,
                    VoteNumber = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteNumber,
                    VoteRate = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteRate,
                    Image = a.Article.Image,
                    Time = a.Article.DisplayDate ?? DateTime.Now,
                    Views = a.Article.Item.ItemView == null ? 0 : a.Article.Item.ItemView.Views,
                })
                .OrderByDescending(a => a.Time);

            totalPage = articles.Count();
            var r = articles.Skip(Skip);
            if (Take > 0) r = r.Take(Take);

            var data = r.ToList();

            var imagePathDetail = string.Format(this._imagePathDetail, companyId);
            var imagePathThumb = string.Format(this._imagePathThumb, companyId);

            foreach (var article in data)
            {
                article.ImagePathDetail = this._url.VirtualPath(imagePathDetail + article.Image);
                article.ImagePathThumb = this._url.VirtualPath(imagePathThumb + article.Image);
            }
            return data;
        }

        public List<ArticlesWithImageViewsDto> GetArticleByCategoryAndType(int categoryId, string languageId, int companyId, string types, out int TotalPage, int Skip = 0, int Take = 0)
        {
            var query = this._articleLanguageDAL.GetAllIncludeItemView()
                .Where(c => c.LanguageId == languageId)
                .Where(c => c.Article.CategoryId == categoryId)
                .Where(c => c.Article.Item.IsPublished && c.Article.Item.CompanyId == companyId);

            var arrType = types.Split(',');
            query = arrType.Aggregate(query, (current, type) => current.Where(c => c.Article.Type.Contains(type)));

            var articles =query.Select(a => new ArticlesWithImageViewsDto
                {
                    Id = a.ArticleId,
                    Title = a.Title,
                    Description = a.Brief,
                    VoteNumber = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteNumber,
                    VoteRate = a.Article.Item.ItemVote == null ? 0 : a.Article.Item.ItemVote.VoteRate,
                    Image = a.Article.Image,
                    Time = a.Article.DisplayDate ?? DateTime.Now,
                    Views = a.Article.Item.ItemView == null ? 0 : a.Article.Item.ItemView.Views,
                })
                .OrderByDescending(a => a.Time);

            TotalPage = articles.Count();
            var r = articles.Skip(Skip);
            if (Take > 0) r = r.Take(Take);

            var data = r.ToList();

            var imagePathDetail = string.Format(this._imagePathDetail, companyId);
            var imagePathThumb = string.Format(this._imagePathThumb, companyId);

            foreach (var article in data)
            {
                article.ImagePathDetail = this._url.VirtualPath(imagePathDetail + article.Image);
                article.ImagePathThumb = this._url.VirtualPath(imagePathThumb + article.Image);
            }
            return data;
        }

        public DataSimpleDto GetDataSingle(int companyId, string languageId, int id)
        {
            var query = this._articleLanguageDAL.GetAll()
                .Where(e => e.Article.Item.CompanyId == companyId && e.LanguageId == languageId && e.Article.Item.IsPublished && !e.Article.Item.HasDeleted && e.ArticleId == id);

            var selected = query.Select(a => new DataSimpleDto
            {
                Id = a.ArticleId,
                CategoryId = a.Article.CategoryId,
                Title = a.Title,
                Description = a.Brief,
                ImagePath = a.Article.Image
            });

            var data = selected.FirstOrDefault();

            if (data != null && !string.IsNullOrEmpty(data.ImagePath))
            {
                var imagePathThumb = string.Format(this._imagePathDetail, companyId);
                data.ImagePath = this._url.VirtualPath(imagePathThumb + data.ImagePath);
            }

            return data;
        }

        public ArticleDetailDto GetArticleDetailById(int id, int companyId, string language)
        {
            var query =
                this._articleLanguageDAL.GetAllIncludeItemView()
                .Where(c => c.Article.Item.CompanyId == companyId && c.Article.Item.HasDeleted == false)
                .Where(c => c.ArticleId == id && c.LanguageId == language)
                .Select(o => new ArticleDetailDto
                {
                    Id = o.ArticleId,
                    Tag = o.Article.Tag,

                    Title = o.Title,
                    Brief = o.Brief,
                    Contents = o.Contents,

                    ImageName = o.Article.Image,

                    Time = o.Article.DisplayDate ?? o.Article.Item.CreateDate,

                    HasComment = o.Article.HasComment ?? false
                });

            var data = query.FirstOrDefault();

            // update path image
            if (data != null)
            {
                if (!string.IsNullOrEmpty(data.ImageName))
                {
                    var imagePathDetail = string.Format(this._imagePathDetail, companyId);
                    var imagePathThumb = string.Format(this._imagePathThumb, companyId);

                    data.ImageThumdPath = this._url.VirtualPath(imagePathThumb + data.ImageName);
                    data.ImageDetailPath = this._url.VirtualPath(imagePathDetail + data.ImageName);
                }

                data.Contents = data.Contents.PageArticleLink("Phần: ");
            }

            return data;
        }
        public ArticleDetailWithViewDto GetArticleDetailWithViewDtoById(int id, int companyId, string language)
        {
            var query =
                this._articleLanguageDAL.GetAllIncludeItemView()
                .Where(c => c.Article.Item.CompanyId == companyId && c.Article.Item.HasDeleted == false)
                .Where(c => c.ArticleId == id && c.LanguageId == language)
                .Select(o => new ArticleDetailWithViewDto
                {
                    Id = o.ArticleId,
                    Tag = o.Article.Tag,

                    Title = o.Title,
                    Brief = o.Brief,
                    Contents = o.Contents,

                    ImageName = o.Article.Image,

                    Time = o.Article.DisplayDate ?? o.Article.Item.CreateDate,
                    Likes = o.Article.Item.ItemLike == null ? 0 : o.Article.Item.ItemLike.Likes,
                    UnLikes = o.Article.Item.ItemLike == null ? 0 : o.Article.Item.ItemLike.UnLikes,
                    Views = o.Article.Item.ItemView == null ? 0 : o.Article.Item.ItemView.Views,
                    VoteNumber = o.Article.Item.ItemVote == null ? 0 : o.Article.Item.ItemVote.VoteNumber,
                    VoteRate = o.Article.Item.ItemVote == null ? 0 : o.Article.Item.ItemVote.VoteRate,
                });

            var data = query.FirstOrDefault();

            // update path image
            if (data != null)
            {
                var imagePathDetail = string.Format(this._imagePathDetail, companyId);
                var imagePathThumb = string.Format(this._imagePathThumb, companyId);

                data.ImageThumdPath = this._url.VirtualPath(imagePathThumb + data.ImageName);
                data.ImageDetailPath = this._url.VirtualPath(imagePathDetail + data.ImageName);

                data.Brief = data.Brief.DeleteHTMLTag().Replace("\r\n", ",");
                data.Contents = data.Contents.PageArticleLink("Phần: ");
            }

            return data;
        }

        public List<RSSDto> GetRSSByCategory(int CategoryId, string LanguageId, out int TotalPage, int Skip = 0, int Take = 0)
        {
            var articles = _articleLanguageDAL.GetAllIncludeItem()
                .Where(c => c.Article.CategoryId == CategoryId)
                .Where(c => c.Article.Item.IsPublished)
                .Select(a => new RSSDto
                {
                    Id = a.ArticleId,
                    Title = a.Title,
                    Descripton = a.Brief,
                    Image = a.Article.Image,
                    Time = a.Article.DisplayDate ?? DateTime.Now,
                }).OrderByDescending(a => a.Time);

            TotalPage = articles.Count();
            var r = articles.Skip(Skip);
            if (Take > 0) r = r.Take(Take);

            return r.ToList();
        }

        public IEnumerable<int> getListCategoryOrderByNewArticle()
        {
            var arts = _articleDAL.GetAllIncludeItem()
                .Where(a => a.Item.IsPublished)
                .OrderByDescending(a => a.DisplayDate)
                .Select(c => c.CategoryId)
                .Distinct()
                .ToArray();

            return arts;
        }
        public CategoryDto[] getListCategoryByListId(IEnumerable<int> arts, string Language)
        {
            var cats_Lang = arts.Join(_categoryLanguageDAL.GetMany(c => c.LanguageId == Language), a => a, c => c.CategoryId, (a, c) => new CategoryDto { ID = c.CategoryId, Title = c.Title }).ToArray();
            return cats_Lang;
        }

        public List<RSSCommentDto> GetCommentForRSS(string Language)
        {
            var tc = _ItemCommentDAL.GetAllIncludeItem();
            var tl = _articleLanguageDAL.GetMany(ca => ca.LanguageId == Language);
            var temp = tc.Join(tl, co => co.ItemId, ca => ca.ArticleId, (co, ca) => new RSSCommentDto
            { 
                User = co.Item.CreateByUser,
                Descripton = co.Description,
                Time = co.Item.CreateDate,
                Id = ca.ArticleId,
                Title = ca.Title })
                .OrderByDescending(c => c.Time)
                .Take(20);
            return temp.ToList();
        }
        #endregion

        #region private Method
        private IQueryable<ArticleLanguage> GetQueryArticles(int companyId, string languageId, int categoryId, bool inChildCat, string types, bool hasFavourite, string tag, int ortherId)
        {
            var query = this._articleLanguageDAL.GetAllIncludeItemView()
                .Where(c => c.LanguageId == languageId && c.Article.Item.CompanyId == companyId)
                .Where(c => c.Article.Item.IsPublished && !c.Article.Item.HasDeleted);

            if (ortherId > 0)
                query = query.Where(language => language.ArticleId != ortherId);

            if (!string.IsNullOrEmpty(tag))
            {
                var arrTag = types.Split('_');
                query = arrTag.Aggregate(query, (current, t) => current.Where(c => c.Article.Tag.Contains(t)));
            }

            if (hasFavourite)
                query = query.OrderBy(language => language.Article.Item.ItemView.Views / ((EntityFunctions.DiffDays((language.Article.Item.ModifyDate ?? language.Article.Item.CreateDate), DateTime.Now) ?? 1) + 1));
            else
                query = query.OrderBy(language => language.Article.Item.Orders)
                    .ThenByDescending(language => language.Article.DisplayDate ?? language.Article.Item.CreateDate)
                    .ThenBy(language => language.Article.CategoryId);

            if (!string.IsNullOrEmpty(types))
            {
                if (!string.IsNullOrEmpty(types))
                {
                    var arrType = types.Split(',');
                    query = arrType.Aggregate(query, (current, type) => current.Where(c => c.Article.Type.Contains(type)));
                }
            }

            if (categoryId > 0)
            {
                IList<int> listCategory;
                if (inChildCat)
                {
                    var categorys = this._categoryLanguageDAL.GetAllIncludeItem()
                        .Where(cat => cat.Category.Item.IsPublished && cat.LanguageId == languageId && cat.Category.Item.CompanyId == companyId)
                        .Select(cat => new CategorySimpleDto
                        {
                            ID = cat.CategoryId,
                            Title = cat.Title,
                            ParentId = cat.Category.ParentId
                        }).ToList();

                    listCategory = this.GetAllChildId(categorys, categoryId);
                }
                else
                {
                    listCategory = new List<int>();
                }

                listCategory.Add(categoryId);
                query = query.Where(c => listCategory.Contains(c.Article.CategoryId));
            }

            return query;
        }

        private IList<int> GetAllChildId(IList<CategorySimpleDto> category, int? parentId)
        {
            var subcats = category.Where(o => o.ParentId == parentId).ToList(); // lay tat ca con cua parentID

            var result = new List<int>();
            foreach (var subcat in subcats)
            {
                if (subcat != null)
                {
                    var temp = this.GetAllChildId(category, subcat.ID);

                    result.Add(subcat.ID);
                    if (temp != null && temp.Count > 0)
                    {
                        result.AddRange(temp);
                    }
                }
            }

            return result;
        }
        #endregion

        public enum OrtherType
        {
            First,
            Last
        }
    }
}
